package com.imooc.business;

import com.imooc.business.domain.Rule;
import com.imooc.business.facade.model.Organ;
import com.imooc.business.facade.model.OrganFacade;
import com.imooc.infra.repository.OrganRepository;
import com.imooc.infra.repository.jdbc.DynamicJdbcRepository;
import com.imooc.infra.repository.jdbc.params.StandardSqlParam;
import com.imooc.module.collect.enums.RuleTypeEnum;
import com.imooc.user.provider.model.UserCenterGroupVo;
import com.imooc.user.provider.model.UserCenterUserVo;
import com.imooc.user.provider.service.UserCenterGroupService;
import com.imooc.user.provider.service.UserCenterUserService;
import lombok.Setter;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author Tim
 * @Description:
 * @Version 1.0
 */
@Service
public class OrganBusiness {

    @Setter(onMethod_ = @Autowired)
    private RuleBusiness ruleBusiness;

    @Setter(onMethod_ = @Autowired)
    private OrganRepository organRepository;

    @Setter(onMethod_ = @Autowired)
    private DynamicJdbcRepository dynamicJdbcRepository;

    @Setter(onMethod_ = @Autowired)
    private OrganFacade organFacade;

    @DubboReference
    private UserCenterGroupService userCenterGroupService;

    @DubboReference
    private UserCenterUserService userService;

    /**
     * 获取进行数据处理的 组织数据
     * @param businessId
     * @param groupIds
     * @param startTime
     * @param endTime
     * @return
     */
    public List<Organ> getRequestOrgans(String businessId, List<String> groupIds,
                                        Date startTime, Date endTime) {
        Rule rule = ruleBusiness.getRule(businessId, RuleTypeEnum.COLLECT.name());
        if (Objects.isNull(rule)) {
            return List.of();
        }
        Long ruleId = rule.getRuleId();
        List<com.imooc.business.domain.Organ> organs = organRepository.listByRuleId(ruleId);
        if (CollectionUtils.isEmpty(organs)) {
            return List.of();
        }
        com.imooc.business.domain.Organ organ = organs.get(0);
        return switch (organ.getCollectWay()) {
            case SQL -> {
                Map<String, Object> params = new HashMap<>();
                params.put(StandardSqlParam.START_TIME, startTime);
                params.put(StandardSqlParam.END_TIME, endTime);
                params.put(StandardSqlParam.GROUP_IDS, groupIds);
                params.put(StandardSqlParam.BUSINESS_ID, businessId);
                List<Organ> groupOrgans = dynamicJdbcRepository.listBeans(organ.getContent(), organ.getDataSource(),
                        Organ.class, params);
                buildOrgans(groupOrgans);
                yield groupOrgans;
            }
            case INTERFACE -> organFacade.fetchBusinessOrgan(organ.getContent(), businessId,
                        groupIds, startTime, endTime);
        };
    }

    private void buildOrgans(List<Organ> groupOrgans) {
        Set<String> groupIds = groupOrgans.stream().map(Organ::getGroupId).collect(Collectors.toSet());
        List<UserCenterGroupVo> groups = userCenterGroupService.getGroupByGroupIds(new ArrayList<>(groupIds));
        Map<String, UserCenterGroupVo> groupId2MapGroup = groups.stream().collect(Collectors.toMap(UserCenterGroupVo::getGroupId, v -> v));

        List<UserCenterUserVo> userVos = userService.getUsersByGroupId(new ArrayList<>(groupIds));
        Map<String, List<UserCenterUserVo>> groupId2MapUser = userVos.stream().collect(Collectors.groupingBy(UserCenterUserVo::getGroupId));

        groupOrgans.stream().peek(organ -> {
            String groupId = organ.getGroupId();
            Optional.ofNullable(groupId2MapGroup.get(groupId)).ifPresent(groupVo -> organ.setSchoolId(groupVo.getParentId()));
            Optional.ofNullable(groupId2MapUser.get(groupId)).ifPresent(users -> organ.setUserIds(users.stream().map(UserCenterUserVo::getId).collect(Collectors.toList())));
        }).collect(Collectors.toList());
    }
}
